﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using System.Windows.Forms;
//using Newtonsoft.Json;
using System.IO.Compression;
using PGMHelper;

namespace OpenSees.XML
{
    /// <summary>
    /// 序列化OpenSees_XML
    /// </summary>
    public partial class OpenSeesXML
    {
        /// <summary>
        /// 反序列化OpenSeesXML
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static BasicXML GetXMLResponse(string filePath)
        {
            //读取整个文件
            List<string> txtList = File.ReadAllLines(filePath).ToList();
            //是否XML文件
            if (!txtList[0].Contains("xml"))
            {
                MessageBox.Show("Target File is not XML Version.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return new BasicXML();
            }
            //文件是否完整
            if (!includeDATA(txtList))
            {
                MessageBox.Show("The Data is Incomplete.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return new BasicXML();
            }
            //文件包含分析结果
            if(!includeResponseType(txtList))
            {
                MessageBox.Show("No ResponseType Existed.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return new BasicXML();
            }
            //判断文件类型
            foreach (string txt in txtList)
            {
                //节点响应
                if (txt.Contains("NodeOutput"))
                    return GetNodeResponse(filePath);
                //层间位移角
                else if (txt.Contains("DriftOutput"))
                    return GetDriftResponse(filePath, txtList, "OpenSeesOutput");
                //单元响应
                else if (txt.Contains("ElementOutput"))
                    return GetElementResponse(filePath);
            }
            MessageBox.Show("Unkown Output Type.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return new BasicXML();
        }

        #region Basic_XML反序列化

        /// <summary>
        /// 反序列化OpenSeesXML
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        private static BasicXML GetNodeResponse(string filePath)
        {
            //序列化分析结果
            return GetBasicXML(DeserializeFromXml<NodeXML>(filePath), filePath);
        }

        /// <summary>
        /// 反序列化单元响应结果
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        private static BasicXML GetElementResponse(string filePath)
        {
            //获得单元响应
            var elementXML = DeserializeFromXml<ElementXML>(filePath);
            //序列化分析结果
            return GetBasicXML(elementXML, filePath);
        }

        /// <summary>
        /// 反序列化层间位移角
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="removeStr"></param>
        /// <returns></returns>
        private static BasicXML GetDriftResponse(string filePath, List<string> strList, string removeStr)
        {
            //创建流
            StreamReader reader = StringToStreamReader(GetStringRemove(strList, removeStr));
            //序列化分析结果
            DriftXML xml = DeserializeFromXml<DriftXML>(reader);
            //序列化分析结果
            return GetBasicXML(xml, filePath);
        }

        /// <summary>
        /// 读取DATA数据
        /// </summary>
        /// <param name="xml"></param>
        /// <param name="filePath"></param>
        /// <returns></returns>
        private static BasicXML GetBasicXML(BasicXML xml, string filePath)
        {
            //分析结果是否为空
            if (!xml.isObjectDeserialize)
            {
                MessageBox.Show("Error ResponseType.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return new BasicXML();
            }
            //获得路径
            xml.FilePath = filePath;
            //从DATA获取分析结果
            xml.isSuccess = xml.SetResultFromData();
            //返回结果
            return xml;
        }

        #endregion

        /// <summary>
        /// 获得文件内容并清楚特殊行
        /// </summary>
        /// <param name="file_path"></param>
        /// <param name="remove_str"> 特殊行关键词 </param>
        /// <returns></returns>
        private static string GetStringRemove(List<string> lineList, string remove_str)
        {
            //存在某元素的行编号
            List<int> index_list = new List<int>();
            //遍历行
            for (int i = lineList.Count - 1; i >= 0; i--)
            {
                if (lineList[i].Contains("OpenSeesOutput"))
                    index_list.Add(i);
            }
            //清除特殊行
            foreach (int index in index_list) lineList.RemoveAt(index);
            //重建行信息
            string str_replace = string.Empty;
            foreach (string line in lineList)
                str_replace += string.Format("{0}\r\n", line);
            return str_replace;
        }

        /// <summary>
        /// 是否存在数据
        /// </summary>
        /// <param name="strList"></param>
        /// <returns></returns>
        private static bool includeDATA(List<string> strList)
        {
            for (int index = strList.Count - 1; index >= 0; index--)
            {
                if (strList[index].Contains("/Data"))
                    return true;
            }
            return false;
        }

        /// <summary>
        /// 是否包含分析结果
        /// </summary>
        /// <param name="strList"></param>
        /// <returns></returns>
        private static bool includeResponseType(List<string> strList)
        {
            foreach (string str in strList)
                if (str.Contains("ResponseType"))
                    return true;
            return false;
        }
    }

    /// <summary>
    /// 序列化OpenSees_XML
    /// </summary>
    public partial class OpenSeesXML
    {
        #region Zip

        /// <summary>
        /// 压缩字符串
        /// </summary>
        /// <param name="str"> 压缩对象 </param>
        /// <returns></returns>
        private static string CompressString(string str)
        {
            var compressBeforeByte = Encoding.GetEncoding("UTF-8").GetBytes(str);
            var compressAfterByte = Compress(compressBeforeByte);
            string compressString = Convert.ToBase64String(compressAfterByte);
            return compressString;
        }

        /// <summary>
        /// 解压字符串
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        private static string DecompressString(string str)
        {
            var compressBeforeByte = Convert.FromBase64String(str);
            var compressAfterByte = Decompress(compressBeforeByte);
            string compressString = Encoding.GetEncoding("UTF-8").GetString(compressAfterByte);
            return compressString;
        }

        /// <summary>
        /// Compress
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private static byte[] Compress(byte[] data)
        {
            try
            {
                var ms = new MemoryStream();
                var zip = new GZipStream(ms, CompressionMode.Compress, true);
                zip.Write(data, 0, data.Length);
                zip.Close();
                var buffer = new byte[ms.Length];
                ms.Position = 0;
                ms.Read(buffer, 0, buffer.Length);
                ms.Close();
                return buffer;

            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }

        /// <summary>
        /// Decompress
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private static byte[] Decompress(byte[] data)
        {
            try
            {
                var ms = new MemoryStream(data);
                var zip = new GZipStream(ms, CompressionMode.Decompress, true);
                var msreader = new MemoryStream();
                var buffer = new byte[0x1000];
                while (true)
                {
                    var reader = zip.Read(buffer, 0, buffer.Length);
                    if (reader <= 0)
                    {
                        break;
                    }
                    msreader.Write(buffer, 0, reader);
                }
                zip.Close();
                ms.Close();
                msreader.Position = 0;
                buffer = msreader.ToArray();
                msreader.Close();
                return buffer;
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }

        #endregion

        #region XML

        /// <summary>
        /// 简单序列化
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private static string SerializeXml(object data)
        {
            using (StringWriter sw = new StringWriter())
            {
                XmlSerializer xz = new XmlSerializer(data.GetType());
                xz.Serialize(sw, data);
                return sw.ToString();
            }
        }

        /// <summary>
        /// 从某一XML文件反序列化到某一类型
        /// </summary>
        /// <param name="filePath">待反序列化的XML文件名称</param>
        /// <param name="type">反序列化出的</param>
        /// <returns></returns>
        private static T DeserializeFromXml<T>(string filePath)
        {
            try
            {
                //文件是否存在
                if (!System.IO.File.Exists(filePath))
                    throw new ArgumentNullException(filePath + " not Exists");
                //读取文件
                using (System.IO.StreamReader reader = new System.IO.StreamReader(filePath))
                    return DeserializeFromXml<T>(reader);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return default(T);
            }
        }

        /// <summary>
        /// 从某一XML文件反序列化到某一类型
        /// </summary>
        /// <param name="filePath">待反序列化的XML文件名称</param>
        /// <param name="type">反序列化出的</param>
        /// <returns></returns>
        private static T DeserializeFromXml<T>(StreamReader sr)
        {
            try
            {
                System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(T));
                T ret = (T)xs.Deserialize(sr);
                return ret;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return default(T);
            }
        }

        /// <summary>
        /// string 转为 streamreader
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        private static StreamReader StringToStreamReader(string str)
        {
            //实力化流
            MemoryStream stream = new MemoryStream();
            StreamWriter writer = new StreamWriter(stream);
            writer.Write(str);
            writer.Flush();
            stream.Position = 0;
            return new StreamReader(stream);
        }

        #endregion
    }

    
}
